package common

import (
	"github.com/sirupsen/logrus"
	"go-proxy/config"
	"io"
	"net"
	"net/http"
	"os"
	"strings"
)

var (
	Logger       *logrus.Logger
	AccessLogger *logrus.Logger
	LogLevelMap  = map[string]logrus.Level{
		"info":  logrus.InfoLevel,
		"error": logrus.ErrorLevel,
		"warn":  logrus.WarnLevel,
		"fatal": logrus.FatalLevel,
		"panic": logrus.PanicLevel,
		"debug": logrus.DebugLevel,
		"trace": logrus.TraceLevel,
	}
)

func LogInit() error {
	commonConfig := config.Config.Common
	var err error
	Logger, err = loggerConfig(&commonConfig.Logger)
	if err != nil {
		return err
	}

	AccessLogger, err = loggerConfig(&commonConfig.AccessLogger)
	if err != nil {
		return err
	}
	return nil
}

func loggerConfig(config *config.LoggerConfig) (*logrus.Logger, error) {
	logger := logrus.New()
	// 设置日志格式
	logger.SetFormatter(&logrus.JSONFormatter{
		TimestampFormat: "2006-01-02 15:04:05",
	})

	// 设置日志级别
	level, ok := LogLevelMap[config.Level]
	if !ok {
		level = logrus.InfoLevel
	}
	logger.SetLevel(level)

	// 设置日志输出到标准输出
	logger.SetOutput(os.Stdout)

	// 如果需要输出到文件
	file, err := os.OpenFile(config.Path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		return nil, err
	}
	logger.SetOutput(file)

	// 设置日志输出到文件和控制台
	multiWriter := io.MultiWriter(os.Stdout, file)
	logger.SetOutput(multiWriter)
	return logger, nil
}

func LogInfo(args ...interface{}) {
	Logger.Info(args...)
}

func LogFatal(args ...interface{}) {
	Logger.Fatal(args...)
}

func LogError(args ...interface{}) {
	Logger.Error(args...)
}

func LogErrorf(format string, args ...interface{}) {
	Logger.Errorf(format, args...)
}

func LogWarning(args ...interface{}) {
	Logger.Warning(args...)
}

func LogDebug(args ...interface{}) {
	Logger.Debug(args...)
}

func LogDebugF(format string, args ...interface{}) {
	Logger.Debugf(format, args...)
}

func LogTrace(args ...interface{}) {
	Logger.Trace(args...)
}

func AccessReqLogInfo(r *http.Request, format string, args ...interface{}) {
	AccessLogger.WithFields(logrus.Fields{
		"host":   r.Host,
		"method": r.Method,
		"path":   r.URL.Path,
		"ip":     getIpAddr(r),
		"header": r.Header,
	}).Infof(format, args...)
}

func AccessRespLogInfo(r *http.Request, resp *http.Response, cost int64, format string, args ...interface{}) {
	AccessLogger.WithFields(logrus.Fields{
		"host":       r.Host,
		"method":     r.Method,
		"path":       r.URL.Path,
		"ip":         getIpAddr(r),
		"statusCode": resp.StatusCode,
		"header":     resp.Header,
		"cost":       cost,
	}).Infof(format, args...)
}

func AccessLogErrorf(r *http.Request, format string, args ...interface{}) {
	AccessLogger.WithFields(logrus.Fields{
		"host":   r.Host,
		"method": r.Method,
		"path":   r.URL.Path,
		"ip":     getIpAddr(r),
	}).Errorf(format, args...)
}

func getIpAddr(r *http.Request) string {
	ip := r.Header.Get("x-forwarded-for")
	if len(ip) > 0 && "unknown" != strings.ToLower(ip) {
		if strings.Contains(ip, ",") {
			ip = strings.Split(ip, ",")[0]
		}
	}
	if len(ip) == 0 || "unknown" == strings.ToLower(ip) {
		ip = r.Header.Get("Proxy-Client-IP")
	}
	if len(ip) == 0 || "unknown" == strings.ToLower(ip) {
		ip = r.Header.Get("WL-Proxy-Client-IP")
	}
	if len(ip) == 0 || "unknown" == strings.ToLower(ip) {
		ip = r.Header.Get("HTTP_CLIENT_IP")
	}
	if len(ip) == 0 || "unknown" == strings.ToLower(ip) {
		ip = r.Header.Get("HTTP_X_FORWARDED_FOR")
	}
	if len(ip) == 0 || "unknown" == strings.ToLower(ip) {
		ip = r.Header.Get("X-Real-IP")
	}
	if len(ip) == 0 || "unknown" == strings.ToLower(ip) {
		ip, _, _ = net.SplitHostPort(strings.TrimSpace(r.RemoteAddr))
	}
	if "0:0:0:0:0:0:0:1" == ip || "::1" == ip {
		ip = "127.0.0.1"
	}
	return ip
}
